package com.lgx.mobile.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Component;

import com.lgx.common.basic.dao.GeneralDao;
import com.lgx.common.basic.dao.GeneralJdbcDao;
import com.lgx.common.exception.DataException;
import com.lgx.common.web.Pagination;
import com.lgx.common.web.util.DateUtils;
import com.lgx.mobile.dao.IGroupDao;
import com.lgx.mobile.entity.Group;
import com.lgx.mobile.vo.GroupVO;

/**
 * 
 * @author xuyichen
 *
 */
@Component("groupDao")
public class GroupDao extends GeneralDao implements IGroupDao {
	
	@Autowired
	private GeneralJdbcDao baseDao;
	
	public GeneralJdbcDao getBaseDao() {
		return baseDao;
	}

	public void setBaseDao(GeneralJdbcDao baseDao) {
		this.baseDao = baseDao;
	}
	
	@Autowired
	private JdbcDaoSupport jdbcDaoSupport;
	
	public JdbcDaoSupport getJdbcDaoSupport() {
		return jdbcDaoSupport;
	}

	public void setJdbcDaoSupport(JdbcDaoSupport jdbcDaoSupport) {
		this.jdbcDaoSupport = jdbcDaoSupport;
	}

	protected Logger log = Logger.getLogger(this.getClass());
	
	public Group createGroup(Group group) throws DataException {
		this.getHibernateTemplate().save(group);
		log.info("[创建圈子]:"+group.getId());
		return group;
	}

	public Group updateGroup(Group group) throws DataException {
		this.getHibernateTemplate().update(group);
		log.info("[更新圈子]:"+group.getId());
		return group;
	}

	public void deleteGroup(Group group) throws DataException {
		log.info("[删除圈子]:"+group.getId());
		this.getHibernateTemplate().delete(group);
	}

	public void deleteGroupById(long id) throws DataException {
		log.info("[删除圈子]:"+id);
		this.deleteGroup(this.findGroupById(id));
	}

	public Group findGroupById(long id) {
		return this.getHibernateTemplate().get(Group.class, id);
	}
	
	@SuppressWarnings("unchecked")
	public Group checkGroupExists(long createUserId,Date createDate,long categoryId){
		String sql = "from Group g where g.createUserId = " + createUserId;
		sql += " and g.createDate = '" + DateUtils.dateToChar(createDate, DateUtils.DATE_FORMAT_D) + "'";
		sql += " and g.categoryId = " + categoryId;
		List<Group> list = this.getHibernateTemplate().find(sql);
		if(list.size() == 0){
			return null;
		}
		return list.get(0);
	}
	
	@SuppressWarnings("unchecked")
	public List<Group> findGroupList(){
		String sql = "from Group g order by g.id asc";
		return this.getHibernateTemplate().find(sql);
	}
	
	@SuppressWarnings("unchecked")
	public List<GroupVO> findHotGroupList(long num){
		String sql = "select g.id as id,";
		sql += "g.name as name,";
		sql += "g.description as description,";
		sql += "g.create_date as createDate,";
		sql += "g.category_id as categoryId,";
		sql += "g.groupimage as groupImage,";
		sql += "g.create_user_id as createUserId,";
		sql += "(select count(*) from tm_m_group_user gu where gu.group_id = g.id) as userNum,";
		sql += "u.nickname as createUserNickName,";
		sql += "u.username as createUserName,";
		sql += "u.truename as createUserTruename,";
		sql += "u.email as createUserEmail,";
		sql += "u.sex as createUserSex,";
		sql += "u.mobile as createUserMobile,";
		sql += "u.card_id as createUserCardId";
		
		sql += " from tm_m_group g inner join ts_user u on g.create_user_id=u.id order by userNum desc limit " + num;
		
		return (List<GroupVO>)baseDao.queryJdbcForList(sql, GroupVO.class);
	}

	@Override
	public Pagination findGroupPagination(Object[] params, Class<?> clazz, int pageSize, int pageNum) {
		String sql = "select * from tm_m_group g order by g.id asc";
		return baseDao.queryJdbcListPagination(sql, clazz, pageSize, pageNum);
	}

	@Override
	public Pagination findMyGroupPagination(long userId, Object[] params, Class<?> clazz, int pageSize, int pageNum) {
		String sql ="select g.id as id, "+
					" 	g.name as name, "+
					" 	g.description as description, "+
					" 	g.create_date as createDate, "+
					" 	g.category_id as categoryId, "+
					" 	g.groupimage as groupImage, "+
					" 	g.create_user_id as createUserId, "+
					" 	u.nickname as createUserNickName, "+
					" 	u.username as createUserName, "+
					" 	u.truename as createUserTruename, "+
					" 	u.email as createUserEmail, "+
					" 	u.sex as createUserSex, "+
					" 	u.mobile as createUserMobile, "+
					" 	u.card_id as createUserCardId,"+
					" 	count(gu.user_id) as userNum"+
					" from tm_m_group g "+
					" left join tm_m_group_user gu on g.id = gu.group_id "+
					" inner join ts_user u on gu.user_id = u.id "+
//					" from ts_user u "+
//					" left join tm_m_group_user gu on u.id = gu.user_id "+
//					" inner join tm_m_group g on gu.group_id=g.id "+
					" where u.id = "+ userId +
					" or g.create_user_id = "+ userId +
					" group by g.id, "+
					" g.name, "+
					" 	g.description, "+
					" 	g.create_date, "+
					" 	g.category_id, "+
					" 	g.groupimage, "+
					" 	g.create_user_id, "+
					" 	u.nickname, "+
					" 	u.username, "+
					" 	u.truename, "+
					" 	u.email, "+
					" 	u.sex, "+
					" 	u.mobile, "+
					" 	u.card_id "+
					" order by g.id ";
		
		String counthql = "select count(*) "+
				" from tm_m_group g "+
				" left join tm_m_group_user gu on g.id = gu.group_id "+
				" inner join ts_user u on gu.user_id = u.id "+
				" where u.id = "+ userId +
				" or g.create_user_id = "+ userId +
				" order by g.id ";
        
		int totalRecordNum = jdbcDaoSupport.getJdbcTemplate().queryForInt(counthql);
		
		pageNum = pageNum -1;
		pageNum = pageNum < 0 ? 0 : pageNum;
		
		String queryhql = sql + " limit " + pageNum*pageSize + " , " + pageSize;
		
		final Class<?> c = clazz;
		List<?> list = jdbcDaoSupport.getJdbcTemplate().query(queryhql, new RowMapper<Object>(){

			public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
				Class<?> obj = null;
				Object t = new Object();
				try {
					obj = Class.forName(c.getName());
					t = (Object) obj.newInstance();
					Field[] fields = obj.getDeclaredFields();
					
					ResultSetMetaData rsmd=rs.getMetaData();
					int columnCount = rsmd.getColumnCount();  
					boolean flag = false;
					int count = 1;
					String fieldName = "";
					String fieldType = "";
				    // 输出列名   
				    for (int i=1; i<=columnCount; i++){  
				    	String name = rsmd.getColumnLabel(i);
				    	if(name.contains("_")){
				    		name = name.split("_")[0]+"Id";
				    	}
				    	
				    	for(Field field : fields){
				    		if(name.toLowerCase().equals(field.getName().toLowerCase())){
				    			flag = true;
				    			count = i;
				    			fieldName = field.getName();
				    			fieldType = field.getType().getSimpleName();
				    			break;
				    		}
				    	}
				        
				        if(flag){

							//首字母大写
							String set = "set"+fieldName.substring(0,1).toUpperCase() + fieldName.substring(1); 
							
							Method method = null;

							if("Long".equals(fieldType))
							{
								method = obj.getMethod(set, Long.class);
								if(method != null)
									method.invoke(t, Long.parseLong(rs.getString(count)));
							}else if("long".equals(fieldType))
							{
								method = obj.getMethod(set, long.class);
								if(method != null)
									method.invoke(t, Long.parseLong(rs.getString(count)));
							}else if("Double".equals(fieldType))
							{
								method = obj.getMethod(set, Double.class);
								if(method != null)
									method.invoke(t, rs.getDouble(count));
							}else if("double".equals(fieldType))
							{
								method = obj.getMethod(set, double.class);
								if(method != null)
									method.invoke(t, rs.getDouble(count));
							}else if("int".equals(fieldType))
							{
								method = obj.getMethod(set, int.class);
								if(method != null)
									method.invoke(t, rs.getInt(count));
							}else if("Integer".equals(fieldType))
							{
								method = obj.getMethod(set, Integer.class);
								if(method != null)
									method.invoke(t, rs.getInt(count));
							}else if("Float".equals(fieldType))
							{
								method = obj.getMethod(set, Float.class);
								if(method != null)
									method.invoke(t, rs.getFloat(count));
							}else if("float".equals(fieldType))
							{
								method = obj.getMethod(set, float.class);
								if(method != null)
									method.invoke(t, rs.getFloat(count));
							}else if("Date".equals(fieldType))
							{
								method = obj.getMethod(set, Date.class);
								if(method != null)
									method.invoke(t, rs.getDate(count));
							}else if("String".equals(fieldType))
							{
								method = obj.getMethod(set, String.class);
								if(method != null)
									method.invoke(t, rs.getString(count));
							}
					    }
				    }   
				   
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				} catch (SecurityException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (InstantiationException e) {
					e.printStackTrace();
				}
				return t;
			}
			
		});
		
		int totalPageNum = totalRecordNum/pageSize;
		if(totalRecordNum%pageSize!=0) {
			totalPageNum+=1;
		}
		Pagination page = new Pagination();
		page.setPageNum(pageNum);
		page.setPageSize(pageSize);
		page.setTotal(totalRecordNum);
		page.setTotalPage(totalPageNum);
		page.setRows(list);
		return page;
	}
}
